/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/** 
 * \file
 * \brief Name mapping table for Nameservice.
 * \author Antti Maula <antti.maula@tkk.fi>
 *
 * Simple module for managing name/nodeid pairs. Performance measures
 * on AMD Athlon(tm) 64 X2 Dual Core Processor 4400+, running on a
 * single core yielded:
 *
 * 1000000 Inserts completed, operation took 5998 ms, 6.00 us per entry
 * 1000000 GetByName:s completed, operation took 2241 ms, 2.24 us per entry
 * 1000000 DeleteEntryByName:s completed, operation took 983 ms, 0.98 us per entry
 * 1000000 Inserts completed, operation took 5945 ms, 5.95 us per entry
 * 1000000 GetByNodeId:s completed, operation took 483 ms, 0.48 us per entry
 * 1000000 DeleteEntryByNodeId:s completed, operation took 758 ms, 0.76 us per entry
 */
#ifndef _GIMNETAP_NAMESERVICE_NAMETABLE_H_
#define _GIMNETAP_NAMESERVICE_NAMETABLE_H_

#include <inttypes.h>
#include <time.h>
#include "nametableentry.h"

// Return values.
#define KNametableResultOK         0
#define KNametableResultConflict   -1
#define KNametableResultError      -2 

/** Initialize nametable.
 *
 * This function initializes the nametable facility. Please note that
 * this module is a standalone, using a common storage for storing
 * names. Hence it is not possible to create separate "instances" of
 * it.
 *
 * @param[in] expected_max_size Expected maximum number of elements in the nametable.
 *                              This value is used to reserve space for the hashing table,
 *                              hence it should be a lot larger than usual average number
 *                              of name/id pairs in use at any given time. Space requirement
 *                              is 3.2Mb for expected_max_size of 1000000 entries. Which is..
 *                              'enough' :)
 */
void nametableInit(const int expected_max_size);


/** Deinitialize module, freeing resources.
 *
 * This function deinitializes the Nametable module, freeing any
 * resources associated.
 */
void nametableDeinit();


/** Insert new entry in nametable.
 *
 * This function attempts to add a new entry in the
 * nametable. Operation will succeed, if neither one of the values; ID
 * or Name, is already in the database. If either one exists, or some other error occurs, the
 * insert will fail (and do nothing).
 *
 * @param[in] name              Name to add
 * @param[in] nodeid            NodeID to bind to name.
 * @param[in] max_age_s         Maximum age for entry, starting from now.
 * @param[out] existing_entry   If non-NULL, pointer to conflicting entry will be stored
 *                              into given address.
 * @return                      zero on success, negative value on error.
 */
int nametableInsertEntry(const char *name, const uint32_t nodeid, 
                         const uint32_t max_age_s, TNameTableEntry const ** existing_entry);


/** Delete entry from nametable - by name.
 *
 * This function deletes an entry from the database, using the name as
 * a key.
 *
 * @param[in] name              Name to search and destroy
 * @return                      zero in case the name/nodeid entry was succesfully deleted,
 *                              negative value in case name was not found, or other error
 *                              occured.
 */
int nametableDeleteEntryByName(const char *name);


/** Delete entry from nametable - by nodeid.
 *
 * This function deletes an entry from the database, using the nodeid as
 * a key.
 *
 * @param[in] nodeid            Nodeid to search and destroy
 * @return                      zero in case the name/nodeid entry was succesfully deleted,
 *                              negative value in case nodeid was not found, or other error
 *                              occured.
 */
int nametableDeleteEntryByNodeId(const uint32_t nodeid);


/** Delete entry from nametable - by TNameTableEntry.
 *
 * This function deletes an entry from the database, using information
 * from a TNameTableEntry. This function is utilized by the other
 * function in the delete family, as they only search for the entry
 * and give it to this function to carry out the deletion process.
 *
 * \note The entry given will be freed before the function returns, hence the
 * given pointer will be invalidated during call.
 *
 * @param[in] entryPtr          Pointer to NameTableEntry to destroy
 * @return                      zero in case the name/nodeid entry was succesfully deleted,
 *                              negative value when some unknown error occured.
 */
int nametableDeleteEntryByEntryPtr(TNameTableEntry *entryPtr);


/** Search for a entry - by name.
 *
 * This function returns a constant pointer to nametable entry
 * containing the given name - if such exists.
 *
 * @param[in] name              Name key to search for.
 * @return                      On successs, pointer to element containing the name,
 *                              or NULL if name was not found from the database.
 */
const TNameTableEntry *nametableGetEntryByName(const char *name);


/** Search for a entry - by nodeid.
 *
 * This function returns a constant pointer to nametable entry
 * containing the given nodeid - if such exists.
 *
 * @param[in] nodeid            Nodeid key to search for.
 * @return                      On successs, pointer to element containing the nodeid,
 *                              or NULL if nodeid was not found from the database.
 */
const TNameTableEntry *nametableGetEntryByNodeId(const uint32_t nodeid);


/** Checks whether the given entry has expired.
 *
 * This function checks whether the given entry is expired. Expiration
 * is calculated by refering the last-update timestamp incremented by
 * max_age to current time.
 *
 * @param[in] entry             Constant pointer to entry to check.
 * @return                      '1' if expired, '0' if not expired.
 *
 */
inline int nametableIsExpiredEntry(const TNameTableEntry *entry);


/** Returns number of seconds before given entry expires.
 *
 * This function returns the number of seconds left before the entry
 * is expired, or zero if the entry has already expired. Function
 * returns negative value in case the entry will never expire (max_age
 * is zero; which is interpreted as inifinite)
 *
 * @param[in] entry             Constant pointer to entry to check.
 * @return                      non-zero number of seconds before the entry
 *                              expires, or zero when entry is already expired.
 *                              -1 is returned when the entry will never expire.
 */
inline long int nametableEntryGetTimeToExpiration(const TNameTableEntry *entry);


/** Update timestamp to current time for given entry.
 *
 * This function updates the timestamp of given entry to current
 * time. This function does not check whether the entry is expired or
 * not, the timestamp is blindly updated.
 *
 * @param[in] entry             Pointer to entry to update.
 */
inline void nametableUpdateTimestamp(TNameTableEntry *entry);


#endif
